#include <sim.h>
#include <gpdr.h>
#include <delay.h>
#include <string.h>
#include <viniSPI.h>

#define CR 0x0D

extern volatile unsigned int sim_status;
extern volatile unsigned char sim_ip[16];



int wait4status(){    
    int i = 0;    
    while(sim_status == SIM_WAIT_CIPSTATUS || sim_status == SIM_WAIT_CIPMUX || sim_status == SIM_WAIT_FTP_OK || sim_status == SIM_WAIT_NETWORK || sim_status == SIM_WAIT_FTP_DATA || sim_status == SIM_NO_STATUS || sim_status == SIM_WAIT_IP || sim_status == SIM_WAIT_CONNECT || sim_status == SIM_WAIT_FTP_CODE || sim_status == SIM_WAIT_FTP_PASV);
    i = sim_status;
    sim_status = SIM_NO_STATUS;
    delay_ms(200);
    return i;
}            

/***********************************************
************** PHONE FUNCTIONS *****************
***********************************************/

int send_text(char* number, char* text){
    if(CGREG() != SIM_OK) return 1;
    if(CMGF("1") != SIM_OK) return 1;   
    if(CSCS() != SIM_OK) return 1;    
    if(CSCA() != SIM_OK) return 1;    
    if(CSMP() != SIM_OK) return 1;
    if(CMGS(number) != SIM_OK) return 1; 
    if(send_message_prompt(text) != SIM_OK) return 1;
    return 0;   
}

int send_textf(flash char* number, flash char* text){
    if(CGREG() != SIM_OK) return 1;
    if(CMGF("1") != SIM_OK) return 1;   
    if(CSCS() != SIM_OK) return 1;    
    if(CSCA() != SIM_OK) return 1;    
    if(CSMP() != SIM_OK) return 1;    
    if(CMGSf(number) != SIM_OK) return 1; 
    if(send_message_promptf(text) != SIM_OK) return 1;  
    return 0; 
    
}

int read_text(char* location){
    if(CMGF("1") != SIM_OK) return 1;    
    if(CMGR(location) != SIM_OK) return 1;
    // Delete the texts we are reading. Can be uncomment if we dont use CALL
    // Because the call is ended if we send another command    
    /*if(CMGD(location) != SIM_OK) return 1;*/
    return 0; 
}

int read_textf(flash char* location){
    if(CMGF("1") != SIM_OK) return 1;    
    if(CMGRf(location) != SIM_OK) return 1;    
    // Delete the texts we are reading. Can be uncomment if we dont use CALL
    // Because the call is ended if we send another command
    /*if(CMGDf(location) != SIM_OK) return 1;*/    
    return 0;  
}

int make_a_call(char* number){
    if(ATD(number) != SIM_OK) return 1;
    return 0;
}

int make_a_callf(flash char* number){
    if(ATDf(number) != SIM_OK) return 1;
    return 0;
}

int delete_all_messages(){
    sim_putstrf("AT+CMGD=0,4\r\n");
    return 0;
}


int send_data_to_ftp(unsigned char* server, unsigned char* port,unsigned char* login, unsigned char* password, unsigned char* file){


    /************************ SIM900 CONFIGURATION ************************/
    
    CIPSHUT(); 
    
    if(CIPMUX() == SIM_CIPMUXZERO){
    
        if(CIPMUXf("1") != SIM_OK) return 1;  
            
        if(CIPHEADf("0") != SIM_OK) return 1;
    }
    
    if(CIPSTATUS() == SIM_CIP_IPINITIAL){
            if(CSTTf("http://m.2degreesmobile.co.nz/") != SIM_OK) return 1;
            if(CIICR() != SIM_OK) return 1;  
            if(CIFSR() != SIM_OK) return 1; 
    }
    else return 1;
    
    
    
    /************************** FTP CONNECTION ***************************/
    
    if(CIPSTART("0","TCP",server, port) != SIM_OK) return 1;
                
    if(CIPSENDf("0") != SIM_OK) {
        CIPCLOSEf("0");
        CIPSHUT();
        return 1;
    } 
    if(FTP_USER(login) != SIM_OK) {
        CIPCLOSEf("0");
        CIPSHUT();
        return 1;
    }  
    
    if(CIPSENDf("0") != SIM_OK) {
        CIPCLOSEf("0");
        CIPSHUT();
        return 1;
    }
    if(FTP_PASS(password) != SIM_OK) {
        CIPCLOSEf("0");
        CIPSHUT();
        return 1;
    }    
             
    if(CIPSENDf("0") != SIM_OK) {
        CIPCLOSEf("0");
        CIPSHUT();
        return 1;
    }  
    if(CWD("/") != SIM_OK) {
        CIPCLOSEf("0");
        CIPSHUT();
        return 1;
    }
    
    if(CIPSENDf("0") != SIM_OK){
        CIPCLOSEf("0");
        CIPSHUT();
        return 1;
    }    
    if(send_ftp_commandf("PWD") != SIM_OK) {
        CIPCLOSEf("0");
        CIPSHUT();
        return 1;
    } 
     
    if(CIPSENDf("0") != SIM_OK) {
        CIPCLOSEf("0");
        CIPSHUT();
        return 1;
    }
    if(send_ftp_commandf("TYPE I") != SIM_OK) {
        CIPCLOSEf("0");
        CIPSHUT();
        return 1;
    }

    if(CIPSENDf("0") != SIM_OK){
        CIPCLOSEf("0");
        CIPSHUT();
        return 1;
    }    
    if(PASV() != SIM_OK){
        CIPCLOSEf("0");
        CIPSHUT();
        return 1;
    }
  
    /************************** SEND FILE *******************************/

    if(CIPSENDf("0") != SIM_OK) {
        CIPCLOSEf("0");
        CIPCLOSEf("1");
        CIPSHUT();
        return 1;
    }    
    
    if(STOR(file) != SIM_OK) {
        CIPCLOSEf("0");
        CIPCLOSEf("1");
        CIPSHUT();
        return 1;
    }
    
    /********************* CLOSE CONNECTIONS*****************************/
      
    CIPCLOSEf("0");
    
    CIPSHUT();
    
    return 0;
}
    

int get_back_data_from_ftp(unsigned char* server, unsigned char* port,unsigned char* login, unsigned char* password, unsigned char* file){
    
    /************************ SIM900 CONFIGURATION ************************/
    
    CIPSHUT(); 
    
    if(CIPMUX() == SIM_CIPMUXZERO){
    
        if(CIPMUXf("1") != SIM_OK) return 1;  
            
        if(CIPHEADf("0") != SIM_OK) return 1;
    }
    
    if(CIPSTATUS() == SIM_CIP_IPINITIAL){
            if(CSTTf("http://m.2degreesmobile.co.nz/") != SIM_OK) return 1;
            if(CIICR() != SIM_OK) return 1;  
            if(CIFSR() != SIM_OK) return 1; 
    }
    else return 1;
    
    
    
    /************************** FTP CONNECTION ***************************/
    
    if(CIPSTART("0","TCP",server, port) != SIM_OK) return 1;
                
    if(CIPSENDf("0") != SIM_OK) {
        CIPCLOSEf("0");
        CIPSHUT();
        return 1;
    } 
    if(FTP_USER(login) != SIM_OK) {
        CIPCLOSEf("0");
        CIPSHUT();
        return 1;
    }  
    
    if(CIPSENDf("0") != SIM_OK) {
        CIPCLOSEf("0");
        CIPSHUT();
        return 1;
    }
    if(FTP_PASS(password) != SIM_OK) {
        CIPCLOSEf("0");
        CIPSHUT();
        return 1;
    }    
             
    if(CIPSENDf("0") != SIM_OK) {
        CIPCLOSEf("0");
        CIPSHUT();
        return 1;
    }  
    if(CWD("/") != SIM_OK) {
        CIPCLOSEf("0");
        CIPSHUT();
        return 1;
    }
    
    if(CIPSENDf("0") != SIM_OK){
        CIPCLOSEf("0");
        CIPSHUT();
        return 1;
    }    
    if(send_ftp_commandf("PWD") != SIM_OK) {
        CIPCLOSEf("0");
        CIPSHUT();
        return 1;
    } 
     
    if(CIPSENDf("0") != SIM_OK) {
        CIPCLOSEf("0");
        CIPSHUT();
        return 1;
    }
    if(send_ftp_commandf("TYPE I") != SIM_OK) {
        CIPCLOSEf("0");
        CIPSHUT();
        return 1;
    }

    if(CIPSENDf("0") != SIM_OK){
        CIPCLOSEf("0");
        CIPSHUT();
        return 1;
    }    
    if(PASV() != SIM_OK){
        CIPCLOSEf("0");
        CIPSHUT();
        return 1;
    }
  
    /************************** RETRIEVE FILE ****************************/
    
    if(CIPSENDf("0") != SIM_OK){
        CIPCLOSEf("0");
        CIPCLOSEf("1");
        CIPSHUT();
        return 1;
    }    
    
    if(RETR(file) != SIM_OK){
        CIPCLOSEf("0");
        CIPCLOSEf("1");
        CIPSHUT();
        return 1;
    }

    /********************* CLOSE CONNECTIONS*****************************/
        
    CIPCLOSEf("1");
     
    CIPCLOSEf("0");
    
    CIPSHUT();
    
    return 0;
}

/*************************************************
************ INTERPRET UART MESSAGES *************
*************************************************/

void sim_interpret_message(){
    char text_location[5];
    int i, i1;
    char delete_r = '\r';
    char delete_n = '\n';    
    char message[100];
    message[0] = '\0';    

    sim_scan(message);     
    delete_char(message, delete_r);
    delete_char(message, delete_n);
    
    
    
    if(message[0] == '' || message[0] == '\0'){  // don't change status
    }
    else if(message[0] == '>'){ // don't change status    
    }
    else if(strncmpf(message , "\r", 1) == 0){  // don't change status  
    }
    else if(strncmpf(message, "\n", 1) == 0){ // don't change status    
    } 
    else if(strncmpf(message, "OK", 2) == 0){ // change status except if we are waiting for the network status, a FTP connection or a PASV message
        if(sim_status != SIM_WAIT_CIPSTATUS && sim_status != SIM_CIPMUXONE && sim_status != SIM_CIPMUXZERO && sim_status != SIM_WAIT_CIPMUX && sim_status != SIM_WAIT_NETWORK && sim_status != SIM_WAIT_CONNECT && sim_status != SIM_WAIT_FTP_PASV) sim_status = SIM_OK;
    }
    else if(strncmpf(message, "CONNECT", 7) == 0){
        sim_status = SIM_CONNECT;
    }
    else if(strncmpf(message, "RING", 4) == 0){
        sim_status = SIM_RING;
    }
    else if(strncmpf(message, "NO CARRIER", 10) == 0){
        sim_status = SIM_NO_CARRIER;
    }
    else if(strncmpf(message, "ERROR", 5) == 0){
        sim_status = SIM_ERROR;
    }
    else if(strncmpf(message, "NO DIALTONE", 11) == 0){
        sim_status = SIM_NO_DIALTONE;
    }
    else if(strncmpf(message, "BUSY", 4) == 0){
        sim_status = SIM_BUSY;
    }
    else if(strncmpf(message, "SHUT OK", 7) == 0){
        sim_status = SIM_SHUT_OK;
    }
    else if(strncmpf(message, "NO ANSWER", 9) == 0){
        sim_status = SIM_NO_ANSWER;  
    }      
    else if(strncmpf(message, "STATE: IP START", 15) == 0){
         sim_status = SIM_CIP_IPSTART;
    }
    else if(strncmpf(message, "STATE: IP INITIAL", 17) == 0){
         sim_status = SIM_CIP_IPINITIAL;
    }
    else if(sim_status == SIM_CIP_IPSTART || sim_status == SIM_CIP_IPINITIAL){
    }
    else if(strncmpf(message, "CONNECT OK", 10) == 0 || strncmpf(message, "0, CONNECT OK", 13) == 0 ||strncmpf(message, "1, CONNECT OK", 13) == 0 ){
        sim_status = SIM_CONNECT_OK;    // The connection is successful 
    }
    else if(strncmpf(message,"CONNECT FAIL", 12) == 0 ||  strncmpf(message, "0, CONNECT FAIL", 15) == 0 || strncmpf(message, "1, CONNECT FAIL", 15) == 0){
        sim_status = SIM_CONNECT_FAIL;
    } 
    else if(strncmpf(message, "CLOSE OK", 8) == 0 || strncmpf(message, "0, CLOSE OK", 11) == 0 ||strncmpf(message, "1, CLOSE OK", 11) == 0 ){
        if(sim_status !=  SIM_WAIT_FTP_DATA) sim_status = SIM_CLOSE_OK;  // The server is closed
    }
    else if(sim_status == SIM_CONNECT_OK){ // do nothing, usefull when we receive useless data from the server after the connection 
        
    }
    else if(strncmpf(message, "SEND OK", 7) == 0 || strncmpf(message, "0, SEND OK", 10) == 0 || strncmpf(message, "1, SEND OK", 10) == 0){
        if(sim_status != SIM_WAIT_FTP_OK && sim_status != SIM_WAIT_FTP_CODE && sim_status != SIM_WAIT_FTP_PASV && sim_status != SIM_WAIT_FTP_DATA) sim_status = SIM_SEND_OK;
        /* We usually do nothing when SEND is OK because we usually want another error code then 
            for instance if we want to send a FTP command, we want the FTP response, not the SEND OK from the dronecell
        */ 
    }
    
    else if(strncmpf(message, "+RECEIVE" ,8) == 0){
        if(sim_status != SIM_WAIT_FTP_OK && sim_status != SIM_WAIT_FTP_CODE && sim_status != SIM_WAIT_FTP_PASV && sim_status != SIM_WAIT_FTP_DATA) sim_status = SIM_FTP_RECEIVE;    
        /* We usually do nothing when we receive +RECEIVE because we usually want something else
            for instance, we will receive +RECEIVE each time we receive a message from the FTP while we want a FTP error code
        */
    }
    else if(sim_status == SIM_WAIT_FTP_OK){
        if(message[0] > 47 && message[0] < 58 && message[1] > 47 && message[1] < 58 && message[2] > 47 && message[2] < 58){ 
            i = (message[0]-48)*100+(message[1]-48)*10+message[2]-48; 
            sim_status = i;
        }
        /* 
            We are waiting a FTP error code, we save the first 3 characters and read it as an integer
            message = "200 Switching to Binary mode." 
            i = 200 
        */
    }
    else if(sim_status == SIM_WAIT_FTP_DATA){
        if(message[0] > 47 && message[0] < 58 && message[1] > 47 && message[1] < 58 && message[2] > 47 && message[2] < 58){ 
            i = (message[0]-48)*100+(message[1]-48)*10+message[2]-48; 
            if(i != 150) sim_status = i;
            /* If a code is received here, that means the file has been received or an error appeared (except for the code 150)  */
        } 
        else {
            /* here is the contents of the file we are retrieving from a FTP */            
        }               
    }  
    else if(sim_status == SIM_WAIT_FTP_CODE){
        i = (message[0]-48)*100+(message[1]-48)*10+message[2]-48; 
        if(i != 220) sim_status = i;
        /* 
            We are waiting a FTP error code, we save the first 3 characters and read it as an integer
            message = "200 Switching to Binary mode." 
            i = 200 
        */                
    } 
    else if(strncmpf(message, "+CIPMUX", 7) == 0){
        if(message[9] == '0') {
            sim_status = SIM_CIPMUXZERO;
        }
        else sim_status = SIM_CIPMUXONE;
    } 
    else if(strncmpf(message, "+CMGR", 5) == 0){  // Reading a text 
        sim_status = SIM_CMGR;       
    }
    else if(strncmpf(message, "+CREG:", 6) ==0){  // Receiving network status
        if(message[7] == '1') sim_status = SIM_NETWORK_OK;
        else sim_status = SIM_ERROR;
    }
    else if(strncmpf(message, "+CGREG:", 7) == 0){  // Receiving network status (this one is used)
        if(message[8] == '1') sim_status = SIM_NETWORK_OK;
        else sim_status = SIM_ERROR;   
    }
    else if(strncmpf(message, "+CMGS:", 6) == 0){  // This is the message received after sending a text
    
    }
    else if(strncmpf(message, "+CMTI", 5) == 0){   // Text received    
        i = 0;        
        while(message[i] != ',' && message[i]) i++; 
        i++;
        i1 = i;       
        while(message[i] != '\0' && i < i1+2){
            text_location[i-i1] = message[i];
            i++;
        }        
        text_location[i-i1] = '\0';
        read_text(text_location); 
        sim_status = SIM_CMTI;    
    }
    else if(sim_status == SIM_WAIT_IP){ /* We are waiting the IP of the dronecell */ 
        for(i = 0; i < strlen(message); i++){
            if(i < 15) sim_ip[i] = message[i];
        }        
        sim_ip[15] = '\0';
        sim_status = SIM_OK;
    }
    else {
        sim_interpret_command(message);
    }
}

void sim_interpret_command(char* command){
    char name_command[SIZE_COMMAND];
    char param1[SIZE_PARAMETER];
    char param2[SIZE_PARAMETER];
    char param3[SIZE_PARAMETER];
    char param4[SIZE_PARAMETER];
    char param5[SIZE_PARAMETER];
    int i = 0, i1 = 0, i2 = 0, i3 = 0, i4 = 0, i5 = 0;
    name_command[0] = '\0';
    param1[0] = '\0';
    param2[0] = '\0';
    param3[0] = '\0';
    param4[0] = '\0';
    param5[0] = '\0';
    
    while(command[i] != ' ' && command[i] != '\0' && i < (SIZE_COMMAND-1)){
        name_command[i] = command[i];
        i++;
    }
    name_command[i] = '\0';
    i1 = i;
    i2 = sim_get_word_from(command, param1, i1);
    i3 = sim_get_word_from(command, param2, i2); 
    i4 = sim_get_word_from(command, param3, i3);  
    i5 = sim_get_word_from(command, param4, i4);  
    sim_get_word_from(command, param5, i5);  
    
    
    if(strncmpf(name_command, "227",3) == 0){ 
        get_ip_port_from_pasv(param4, param1, param2);
        CIPSTART("1","TCP",param1,param2);           
    }                               
    else if(strncmpf(name_command, "GET_DATA_FTP", 12)==0){
        get_back_data_from_ftp(param1, param2, param3, param4, param5);        
    } 
    else if(strncmpf(name_command, "SEND_TO_FTP", 11)==0){
        send_data_to_ftp(param1, param2, param3, param4, param5);        
    }   
    else if(strncmpf(name_command, "SEND_TEXT", 9) == 0){
        sim_get_end_from(command, param2, i2); 
        send_text(param1, param2);         
    }    
    else if(strncmpf(name_command, "CALL", 4) == 0){
        delay_ms(5000);
        make_a_call(param1);
        delay_ms(5000);
        CIPSHUT();
    }    
    else{
        sim_status = SIM_UNKWOWN;

    }
                  
}

void sim_scan(char* message){
    char c;
    int i = 0;
    c = sim_getchar();
   
    while(c){  
        message[i] = c;
        i++;
        c = sim_getchar();
    } 
    message[i] = '\0';
}

/**************************************************
************* BASIC C FUNCTIONS *******************
**************************************************/

void delete_char(char* message, char c){
    int id_read, id_write;
    id_read = 0;
    id_write = 0;
    while (message[id_read] != '\0'){
        if (message[id_read] != c){
            message[id_write] = message[id_read];
            id_write++;
        }
        id_read++;
    }
    message[id_write] = '\0';
}

void get_ip_port_from_pasv(char* param4, char* param1, char* param2){
    int i=0, j=0, k=0, l=0,m=0;
    unsigned int port=0;
    char port1[3];
    char port2[3];
    char portc[6];
    param1[0] = '\0';
    param2[0] = '\0';  
    while(param4[i] != ')'){
        if(param4[i] == ','){
            j++;
            if(j < 4){
                param1[m] = '.';
                m++;
            }
        }
        else if(j == 4){
            port1[k] = param4[i];
            k++;
        }
        else if(j == 5){
            port2[l] = param4[i];
            l++;
        }
        else if(j < 4 && param4[i] != '('){
            param1[m] = param4[i];
            m++;
        }
        i++;
    }
    param1[m] = '\0';
    sim_putstr(param1);
    if(k == 1) port = (port1[0]-48)*256;
    else if(k == 2) port = ((port1[0]-48)*10+port1[1]-48)*256;    
    else if(k ==3) port = ((port1[0]-48)*100+(port1[1]-48)*10+port1[2]-48)*256;


    if(l == 1) port += (port2[0]-48);
    else if(l == 2) port += ((port2[0]-48)*10+port2[1]-48);    
    else if(l ==3) port += ((port2[0]-48)*100+(port2[1]-48)*10+port2[2]-48);

    for(i = 5; i >= 0; i--){
        portc[i] = (port%10)+48;
        port/=10;
    }
    i=0;
        
    while(portc[i] == '0') i++;

    k=0;
    for(i=i; i < 6; i++){
        param2[k] = portc[i];
        k++;
    }
    param2[k] = '\0';
}
         
int sim_get_word_from(char* command, char* param, int i){
    int k=0;
    if(command[i] == ' ') i++;
    while(command[i] != '\0' && command[i] != ' ' && k < (SIZE_PARAMETER-1)){
        param[k] = command[i];
        k++;
        i++;
    }
    param[k] = '\0';
    return i;
}

void sim_get_end_from(char* command, char* param, int i){
    int k=0;
    if(command[i] == ' ') i++;
    while(command[i] != '\0' && k < (SIZE_PARAMETER-1)){
        param[k] = command[i];
        k++;
        i++;
    }
    param[k] = '\0';
    
}

/**************************************************
*************** AT COMMANDS ***********************
**************************************************/


int CGREG(){
    sim_status = SIM_NO_STATUS;
    sim_putstrf("AT+CGREG?\r\n");
    if(wait4status() != SIM_OK) return 0;
    sim_status = SIM_WAIT_NETWORK;
    sim_putstrf("AT+CGREG?\r\n");
    if(wait4status() == SIM_NETWORK_OK) return 1;
    else return 0;
}

int CMGF(flash unsigned char* i){
    sim_status = SIM_NO_STATUS;
    sim_putstrf("AT+CMGF=");
    sim_putstrf(i);
    sim_putstrf("\r\n");
    return wait4status(); // OK or ERROR
}

int CSCS(){
    sim_status = SIM_NO_STATUS;
    sim_putstrf("AT+CSCS=\"GSM\"\r\n");
    return wait4status(); // OK or +CME ERROR or ERROR
}

int CSCA(){ 
    sim_status = SIM_NO_STATUS;
    sim_putstrf("AT+CSCA=\"+64220227672\"\r\n");
    return wait4status(); // OK or +CMS ERROR or ERROR
} 

int ATD(char* number){
    CIPSHUT();
    sim_status = SIM_NO_STATUS;
    sim_putstrf("ATD");
    sim_putstr(number);
    sim_putstrf(";\r\n");;
    return wait4status(); // OK or NO CARRIER or NO DIALTONE or +CME ERROR or BUSY or NO ANSWER
}

int ATDf(flash char* number){
    sim_status = SIM_NO_STATUS;
    sim_putstrf("ATD");
    sim_putstrf(number);
    sim_putstrf(";\r\n");
    return wait4status(); // OK or NO CARRIER or NO DIALTONE or +CME ERROR or BUSY or NO ANSWER
}

int CMGR(char* location){
    sim_status = SIM_NO_STATUS;
    sim_putstrf("AT+CMGR=");
    sim_putstr(location);
    sim_putstrf("\r\n");
    if(wait4status() == SIM_CMGR) return 1; // +CMGR: or +CMS ERROR
    else return 0;
}

int CMGRf(flash char* location){
    sim_status = SIM_NO_STATUS;
    sim_putstrf("AT+CMGR=");
    sim_putstrf(location);
    sim_putstrf("\r\n");
    if(wait4status() == SIM_CMGR) return 1; // +CMGR: or +CMS ERROR
    else return 0;
}

int CMGD(char* location){ 
    sim_status = SIM_NO_STATUS;
    sim_putstrf("AT+CMGD=");
    sim_putstr(location);
    sim_putstrf("\r\n");
    return wait4status(); // OK or ERROR or +CMS ERROR
}

int CMGDf(flash char* location){ 
    sim_status = SIM_NO_STATUS;
    sim_putstrf("AT+CMGD=");
    sim_putstrf(location);
    sim_putstrf("\r\n");
    return wait4status(); // OK or ERROR or +CMS ERROR
}

int CSMP(){
    sim_status = SIM_NO_STATUS;
    sim_putstrf("AT+CSMP=17,167,0,241\r\n");  
    return wait4status(); // OK
}  
                 
int CMGS(unsigned char* number){  
    sim_status = SIM_NO_STATUS;         
    sim_putstrf("AT+CMGS=\"");
    sim_putstr(number);
    sim_putstrf("\"\r\n"); 
    delay_ms(200);
    return 1;
}

int CMGSf(flash unsigned char* number){
    sim_status = SIM_NO_STATUS;         
    sim_putstrf("AT+CMGS=\"");
    sim_putstrf(number);
    sim_putstrf("\"\r\n"); 
    delay_ms(200);
    return 1;
}

int send_message_prompt(unsigned char* text){
    sim_status = SIM_NO_STATUS;
    sim_putstr(text);
    sim_putchar(26); 
    return wait4status();
}



int send_message_promptf(flash unsigned char* text){
    sim_status = SIM_NO_STATUS;
    sim_putstrf(text);
    sim_putchar(26); 
    return wait4status(); 
}

int CIPCLOSEf(flash unsigned char* i){
    sim_status = SIM_NO_STATUS;
    if(i == ""){
        sim_putstrf("AT+CIPCLOSE\r\n");
    }
    else{
        sim_putstrf("AT+CIPCLOSE=");
        sim_putstrf(i);
        sim_putstrf("\r\n");
    }
    
    if(wait4status() == SIM_CLOSE_OK) return 1; // CLOSE OK or ERROR
    else return 0;
}    



int CIPSENDf(flash unsigned char* i){
    sim_status = SIM_NO_STATUS;
    if(i==""){
        sim_putstrf("AT+CIPSEND\r\n");
    }
    else{
        sim_putstrf("AT+CIPSEND=");
        sim_putstrf(i);
        sim_putstrf("\r\n");
    }
    delay_ms(200);
    return 1;
}

int CSTTf(flash unsigned char* address){
    sim_status = SIM_NO_STATUS;
    sim_putstrf("AT+CSTT=\"");
    sim_putstrf(address);
    sim_putstrf("\",\"\",\"\"\r\n");
    return wait4status();  // OK or ERROR
}

int CIPHEADf(flash unsigned char* i){
    sim_status = SIM_NO_STATUS;
    sim_putstrf("AT+CIPHEAD=");
    sim_putstrf(i);
    sim_putstrf("\r\n");
    return wait4status(); // OK or ERROR    
}

int CIICR(){   
    sim_status = SIM_NO_STATUS;
    sim_putstrf("AT+CIICR\r\n");
    return wait4status(); // OK or ERROR
} 

int CIFSR(){ 
    int i = 0;
    for(i = 0; i < 15; i++){
        sim_ip[i] = ' ';
    } 
    sim_ip[15] = '\0';
    sim_status = SIM_WAIT_IP;   
    sim_putstrf("AT+CIFSR\r\n");
    wait4status();
    
    if(sim_ip[0] != ' ') return 1;
    else return 0;
}

int CIPMUX(){
    sim_status = SIM_WAIT_CIPMUX;
    sim_putstrf("AT+CIPMUX?\r\n");
    return wait4status();
}

int CIPMUXf(flash unsigned char* i){
    
    sim_status = SIM_NO_STATUS;
    sim_putstrf("AT+CIPMUX=");
    sim_putstrf(i);
    sim_putstrf("\r\n");
    return wait4status(); // OK or ERROR 
}
 

int CIPSHUT(){
    int i;
    sim_status = SIM_NO_STATUS;
    sim_putstrf("AT+CIPSHUT\r\n");
    i = wait4status();
    if(i == SIM_SHUT_OK) return 2;
    else if(i == SIM_OK) return 1;
    else return 0; // OK or SHUT OK or ERROR
}

int CIPSTART(flash unsigned char* number, flash unsigned char* mode, unsigned char* server, unsigned char* port){
    int i;
    if(sim_status != SIM_WAIT_FTP_PASV) sim_status = SIM_WAIT_CONNECT;
    sim_putstrf("AT+CIPSTART=");
    sim_putstrf(number);
    sim_putstrf(",\"");
    sim_putstrf(mode);
    sim_putstrf("\",\"");
    sim_putstr(server);
    sim_putstrf("\",\"");
    sim_putstr(port);
    sim_putstrf("\"\r\n"); 
    if(sim_status != SIM_WAIT_FTP_PASV){
        i = wait4status();
        
        if(i == SIM_CONNECT_OK) return 1;
        else if(i == SIM_CONNECT_FAIL){
            CIPSHUT();
            return 0;
        }
        else return 0; // OK or number, CONNECT OK or number, ALREADY CONNECT or number, CONNECT FAIL or +CME ERROR
    }
    else return 1;
} 

int CIPSTATUS(){
    sim_status = SIM_WAIT_CIPSTATUS; 
    sim_putstrf("AT+CIPSTATUS\r\n");
    return wait4status();   
} 


/**************************************************
*************** FTP COMMANDS **********************
**************************************************/
    
int RETR(char* file){
    sim_status = SIM_WAIT_FTP_DATA;
    /*open_file4write(file, '0');*/
    sim_putstrf("RETR ");
    sim_putstr(file);
    sim_putstrf("\r\n");
    sim_putchar(26);
    if(wait4status() == 226) return 1;
    else return 0;
}

int STOR(char* file){
    int i = 0;
    unsigned char c;
    unsigned char minibuffer[4];
    sim_status = SIM_WAIT_FTP_OK;
    sim_putstrf("STOR ");
    sim_putstr(file);
    sim_putstrf("\r\n");
    sim_putchar(26);   
    
    if(wait4status() != 150) return 0;
    
    
    putstrf("RD ");
    putstr(file);
    putchar(CR);
    
    sim_status = SIM_NO_STATUS;
    if(CIPSENDf("1") != SIM_OK) return 1;
    
    
    for(i = 0; i < 5; i++) rx2buffer(1);    
    i=0;
    while(i < 4){
        c = rx2buffer(1); 
	    if((i == 0 && c == 'D') || (i == 1 && c == ':') || (i == 2 && c == 92) || (i == 3 && c == '>')){
	        minibuffer[i] = c;
	        i++;
	    }
	    else{
	        if(i != 0){
	            sim_putstr(minibuffer);
                while(i != 0){
                    minibuffer[i] = '';
                    i--;
                }
	            i = 0;
	        }
	        if(c != 26 && c != 27) sim_putchar(c);
            else sim_putchar(28);
	    }
    }
    
    sim_putchar(26);
    delay_ms(200);
    
    sim_status = SIM_WAIT_FTP_DATA;
    sim_putstrf("AT+CIPCLOSE=1\r\n");    
   
    if(wait4status() == 226) return 1;
    else return 0;

}
   
int send_ftp_commandf(flash unsigned char* command){ 
    int i; 
    sim_status = SIM_WAIT_FTP_CODE;  
    sim_putstrf(command);
    sim_putstrf("\r\n");
    sim_putchar(26); 
    i = wait4status();
    if(i == 227 || i == 200 || i == 257) return 1;
    else return 0;  
}


int CWD(flash unsigned char* directory){
    int i;
    sim_status = SIM_WAIT_FTP_CODE;  
    sim_putstrf("CWD ");
    sim_putstrf(directory);
    sim_putstrf("\r\n");
    sim_putchar(26); 
    i = wait4status();
    if(i == 250) return 1;
    else return 0;    
}


int FTP_USER(unsigned char* login){
    sim_status = SIM_WAIT_FTP_CODE;
    sim_putstrf("USER ");
    sim_putstr(login);   
    sim_putstrf("\r\n");
    sim_putchar(26); 
    
    if(wait4status() == 331) return 1;
    else return 0; 
}    

int FTP_PASS(unsigned char* password){
    sim_status = SIM_WAIT_FTP_CODE;    
    sim_putstrf("PASS ");
    sim_putstr(password);   
    sim_putstrf("\r\n");    
    sim_putchar(26); 
    
    if(wait4status() == 230) return 1;
    else return 0;
}

int PASV(){   
    sim_status = SIM_WAIT_FTP_PASV;
    sim_putstrf("PASV \r\n");    
    sim_putchar(26);    
    if(wait4status() == SIM_CONNECT_OK) return 1;
    else return 0;
}